﻿using Me.Framework.Xml.XmlAttr;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Me.Framework.Xml.Base
{
    public abstract class XmlHelper
    {

        #region "==================================Load Xml=================================="

        protected virtual XmlDocument LoadXml(string uri, string xml)
        {
            XmlDocument xmlDoc = new XmlDocument();
            if (uri == null || uri == "")
                xmlDoc.LoadXml(xml);
            else
                xmlDoc.Load(uri);
            return xmlDoc;
        }

        protected virtual XmlElement LoadRootNode(string uri, string xml)
        {
            XmlDocument xmlDoc = LoadXml(uri,xml);
            XmlElement xe = xmlDoc.DocumentElement;
            return xe;
        }

        protected virtual XmlDocument Load(string xml)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xml);
            return xmlDoc;
        }

        #endregion "==================================Load Xml=================================="

        #region "==================================获取模型配置的属性=================================="
        /// <summary>
        /// 获取模型配置的依赖属性
        /// </summary>
        /// <typeparam name="T">NodeAttrAttribte,NodeNameAttribute,RootNodeAttribute</typeparam>
        /// <param name="type">类型</param>
        /// <param name="attributeName">依赖属性名称</param>
        /// <returns>属性上配置的依赖属性的名称</returns>
        protected virtual string GetNodeAttrName<T>(Type type, string attributeName) where T : Attribute
        {
            var attr = type.GetCustomAttribute<T>(false);
            //CheckException(attr);
            string name = GetNodeAttrName<T>(attr, attributeName);
            return name;
        }

        /// <summary>
        /// 获取模型配置的依赖属性
        /// </summary>
        /// <typeparam name="T">NodeAttrAttribte,NodeNameAttribute,RootNodeAttribute</typeparam>
        /// <param name="property">属性</param>
        /// <param name="attributeName">依赖属性名称</param>
        /// <returns>属性上配置的依赖属性的名称</returns>
        protected virtual string GetNodeAttrName<T>(PropertyInfo property, string attributeName) where T : Attribute
        {
            var attr = property.GetCustomAttribute<T>(false);
            //CheckException(attr);
            string name = GetNodeAttrName<T>(attr, attributeName);
            return name;
        }

        protected virtual string GetNodeName(Type type)
        {
            var attr = type.GetCustomAttribute(typeof(RootNodeAttribute), false);
            if (attr == null)
                attr = type.GetCustomAttribute(typeof(NodeNameAttribute), false);
            object nodeName = attr.GetType().GetProperty("Name").GetValue(attr);
            if (nodeName == null)
                nodeName = type.Name;

            return nodeName.ToString();

        }

        /// <summary>
        /// 异常检查
        /// </summary>
        /// <param name="attr"></param>
        private void CheckException(object attr)
        {
            if (attr == null)
                throw new Exception("信息配置错误,请检查模型是否正确!");
        }

        /// <summary>
        /// 获取模型配置的依赖属性（提供于上面调用）
        /// </summary>
        /// <typeparam name="T">NodeAttrAttribte,NodeNameAttribute,RootNodeAttribute</typeparam>
        /// <param name="attr">T</param>
        /// <param name="attributeName">依赖属性名称</param>
        /// <returns>属性上配置的依赖属性的名称</returns>
        private string GetNodeAttrName<T>(T attr, string attributeName) where T : Attribute
        {
            var temp = attr.GetType().GetProperty(attributeName).GetValue(attr);
            if (temp == null || temp == "")
                return null;
            return temp.ToString();
        }

        #endregion "==================================获取模型配置的属性=================================="

        #region "==================================检查是否是节点、属性、根节点=================================="

        protected virtual bool CheckIsAttribute(PropertyInfo proerty)
        {
            if (proerty.IsDefined(typeof(NodeAttrAttribute), false))
                return true;
            return false;
        }

        #endregion "==================================检查是否是节点、属性、根节点=================================="

        #region "==================================Check=================================="
        protected bool CheckIsCollection(Type type)
        {
            var temp = Activator.CreateInstance(type, null);
            if (temp is IEnumerable)
                return true;
            return false;
        }

        protected bool CheckIsCollection(object obj)
        {
            if (obj is IEnumerable)
                return true;
            return false;
        }

        protected bool CheckIsSysType(Type type)
        {
            if (type is IConvertible)
                return true;
            return false;
        }

        protected bool CheckIsRootNode(Type type)
        {
            var attr = type.GetCustomAttribute<RootNodeAttribute>(false);
            if (attr == null)
                return false;
            return true;
        }
        #endregion "==================================Check=================================="



        #region "==================================Obj To Xml Format=================================="

        protected virtual string BeginTag(string name)
        {
            string result = "<" + name + ">";
            return result;
        }

        protected virtual string BeginTag(string name, string attribute)
        {
            string result = "<" + name + " " + attribute + ">";
            return result;
        }

        protected virtual string CloseTag(string name)
        {
            string result = "</" + name + ">";
            return result;
        }

        protected virtual string AppendSpace(int count) 
        {
            string result = "";
            for (int i = 0; i < count; i++)
            {
                result += "\0";
            }

            return result;
        }
        #endregion "==================================Obj To Xml Format=================================="
    }
}
